﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cool.Application.System.DeptService.Dtos;
using Cool.Application.System.MenuService.Dtos;
using Cool.Core.ComDto;
using Cool.Core.Entities.System;
using Cool.Core.Enums;
using Cool.Core.Managers;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Cool.Application.System.DeptService
{
    [Authorize]
    [ApiDescriptionSettings("System")]
    [Route("api/system/[controller]")]
    public class DeptService:IDeptService, ITransient, IDynamicApiController
    {
        /// <summary>
        /// 部门仓储
        /// </summary>
        private readonly IRepository<SysDept> _deptRepository;

        /// <summary>
        /// 用户管理类
        /// </summary>
        private readonly IUserManager _userManager;

        /// <summary>
        /// 角色部门仓储
        /// </summary>
        private readonly IRepository<SysRoleDept> _roleDeptRepository;

        private readonly Func<List<DeptTreeTableReturnDto>, int, List<DeptTreeTableReturnDto>> func = null;
        private readonly Func<List<SysDept>, int, List<TreeOutData>> deptMenuFunc = null;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="deptRepository"></param>
        /// /// <param name="userManager"></param>
        public DeptService(IRepository<SysDept> deptRepository, IUserManager userManager, IRepository<SysRoleDept> roleDeptRepository)
        {
            _deptRepository = deptRepository;
            _userManager = userManager;
            _roleDeptRepository = roleDeptRepository;

            func = delegate (List<DeptTreeTableReturnDto> allList, int parentId)
            {
                var childrenList = allList.Where(p => p.ParentId == parentId).OrderBy(p => p.OrderNum).ToList();
                foreach (var menuList in childrenList)
                {
                    menuList.children = func(allList, menuList.Id);
                }
                return childrenList;
            };

            deptMenuFunc = delegate (List<SysDept> allList, int parentId)
            {
                var childrenList = allList.Where(p => p.ParentId == parentId).OrderBy(p => p.OrderNum).ToList();
                var treeDataOuts = new List<TreeOutData>();
                foreach (var menuList in childrenList)
                {
                    var menuOutData = new TreeOutData
                    {
                        Id = menuList.Id,
                        Label = menuList.DeptName
                    };
                    menuOutData.Children = deptMenuFunc(allList, menuList.Id);
                    treeDataOuts.Add(menuOutData);
                }
                return treeDataOuts;
            };
        }

        #region 部门配置页面接口

        public async Task<List<DeptTreeTableReturnDto>> GetListAsync([FromQuery] DeptTreeTableSearchDto deptTreeTableSearchDto)
        {
            var hasDeptName = !string.IsNullOrEmpty(deptTreeTableSearchDto.DeptName?.Trim());
            var hasStatus = deptTreeTableSearchDto.Status != null;

            var deptTreeList = await _deptRepository.Where(
                (hasDeptName, u => EF.Functions.Like(u.DeptName, $"%{deptTreeTableSearchDto.DeptName.Trim()}%")),
                (hasStatus, u => u.Status == deptTreeTableSearchDto.Status)
            ).ToListAsync();

            var adaptTreeList = deptTreeList.Adapt<List<DeptTreeTableReturnDto>>();

            return func(adaptTreeList, -1);
        }

        public async Task<List<TreeOutData>> GetTreeSelect()
        {
            var allList = await _deptRepository.AsQueryable().ToListAsync();
            return deptMenuFunc(allList, -1);
        }

        public async Task<dynamic> GetRoleDeptTreeSelect([Required, Range(1, int.MaxValue, ErrorMessage = "请输入有效的角色 Id")] int roleId)
        {
            var depts = await GetTreeSelect();
            var roleList = await _roleDeptRepository.Where(p => p.RoleId == roleId).ToListAsync();

            return new
            {
                depts,
                checkedKeys = roleList.Select(p => p.DeptId).ToArray()
            };
        }

        public async Task<List<DeptTreeTableReturnDto>> GetListDeptExcludeChild( int deptId)
        {
            var deptTreeList = await _deptRepository.Where(
                p=>p.Id!=deptId
            ).ToListAsync();

            var adaptTreeList = deptTreeList.Adapt<List<DeptTreeTableReturnDto>>();

            return func(adaptTreeList, -1);
        }

        public async Task<SysDept> GetAsync([Required, Range(1, int.MaxValue, ErrorMessage = "请输入有效的部门 Id")] int deptId)
        {
            return await _deptRepository.FindAsync(deptId);
        }

        public async Task<SysDept> AddAsync([Required] SysDept menu)
        {
            var entryEntity = await _deptRepository.InsertAsync(menu);
            return entryEntity.Entity;
        }

        public async Task UpdateAsync([Required] SysDept dept)
        {
            await _deptRepository.UpdateExcludeAsync(dept, new[] { nameof(SysDept.IsDeleted), nameof(SysDept.CreatedTime) }, ignoreNullValues: true);
        }

        public async Task DeleteAsync([Required, Range(1, int.MaxValue, ErrorMessage = "请输入有效的部门 Id")] int deptId)
        {
            var deleteMenu = await _deptRepository.FindAsync(deptId);
            _ = deleteMenu ?? throw Oops.Oh(SystemErrorCodes.u1002);

            // 软/假删除
            deleteMenu.IsDeleted = true;
        }

        #endregion
    }
}
